package civicinity.ist.psu.edu.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.Facebook;
import com.facebook.android.FacebookError;
import com.facebook.android.Util;

import civicinity.ist.psu.edu.R;
import civicinity.ist.psu.edu.constants.Constants;
import civicinity.ist.psu.edu.databases.CivicinityDatabase;
import civicinity.ist.psu.edu.facebook.BaseRequestListener;
import civicinity.ist.psu.edu.facebook.SessionStore;
import civicinity.ist.psu.edu.rssfeed.RSSReader;
import civicinity.ist.psu.edu.share.CivicinityMyView;
import civicinity.ist.psu.edu.share.ShareItem;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

public class UploadHandler {
	
	private Context mContext;
	private static final String pathname = "/sdcard/Loci/Data/Tmp/";
	//private String mIMEI = LociMobileManagerService.getInstance().IMEI;
	private static SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd");
	
	private String mUsername;
	private String mEmail;
	
	private String responseResult;
	
	private CivicinityDatabase mDB;
	private SharedPreferences mPref;
	
	private int mEventID;
	
    private Facebook mFacebook;
    private AsyncFacebookRunner mAsyncRunner;
	
	public UploadHandler(Context context) {
		mContext = context;
		mDB = new CivicinityDatabase(context);
		mPref = PreferenceManager.getDefaultSharedPreferences(context);
		//mUsername = loadUsername();
		//mEmail = loadUseremail();
		
		//Toast.makeText(mContext, "Uploading your data to the server", Toast.LENGTH_SHORT).show();
	}
	
	public void upload(int id, boolean checkFacebook) {
		
		mEventID = id;
		
		if (Looper.myLooper() == null)
			Looper.prepare();
		
		Uploader uploader = new Uploader(id, checkFacebook);
		uploader.execute();
		
	}
	
	public void createFacebookAssociates(String name) {
		
	}
	
	public void uploadEvent(int eventID, double latitude, double longitude, float accuracy, String imagePath) {
		if (Looper.myLooper() == null)
			Looper.prepare();
		
		UploaderEvent eUpload = new UploaderEvent(eventID, latitude, longitude, accuracy, imagePath);
		eUpload.execute();
	}
	
	/**
	 * like uploader
	 * @param shareID : the id correspond to the photo.
	 * @param userID : my user id
	 */
	public void uploadLike(int shareID, int userID) {
		if (Looper.myLooper() == null)
			Looper.prepare();
		
		HttpClient httpclient = new DefaultHttpClient();  		    
	    String url = new String(Constants.UPLOAD_LIKE);
	    HttpPost httppost = new HttpPost(url);
	    
	    Log.i("K", "start uploading like.");
	    
	    // add values and using library
	    MultipartEntity entity = new MultipartEntity();
	    
	    try {
	    	entity.addPart("l_share_id", new StringBody(String.valueOf(shareID)));
		 	entity.addPart("l_user_id", new StringBody(String.valueOf(1))); // temporarily insert 1.
        	
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	   
	    httppost.setEntity(entity);
	    HttpResponse response = null;
	    responseResult = "";	
	    try {
			response = httpclient.execute(httppost);
			if (response != null) {
				if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				
					BufferedReader br = null;
					try {
						br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
					} catch (IllegalStateException e) {
						Log.i("K", "doInBackground: bufferedReader failed. Illegal.");
						e.printStackTrace();
					} catch (IOException e) {
						Log.i("K",  "doInBackground: bufferedReader failed. IOException.");
						e.printStackTrace();
					} 
					
					try {
						
						for(;;) {
							String line = br.readLine();
							
							Log.i("K", "line :" + line);
							
							if(line == null) {
								responseResult = "UPLOADED_FAILED";
								Log.i("K", "doInBackground: Upload failed");
								break;
							}
							
							if(line.equals("UPLOADED_OK")) {
								responseResult = "UPLOADED_OK";
								Log.i("K", "doInBackground: Upload ok");
								break;
							}
						}
					
					} catch (IOException e) {
						Log.i("K", "doInBackground: br.readLine() failed IOException.");
						e.printStackTrace();
					}
				} 
				else {
					Log.i("K", "doInBackground: NOT SC_OK");				
				}
			} 
		} catch (ClientProtocolException e) {
			//e.printStackTrace();
			
		} catch (IOException e) {
			//e.printStackTrace();
		}
	}
	
	/**
	 * 
	 * @param shareID : current here&now event id
	 * @param date : current date
	 * @param userID : user id
	 */
	
	public void uploadCheckIn(int shareID, long date) {
		if (Looper.myLooper() == null)
			Looper.prepare();
		
		HttpClient httpclient = new DefaultHttpClient();  		    
	    String url = new String(Constants.UPLOAD_MY_CHECK_IN);
	    HttpPost httppost = new HttpPost(url);
	    
	    
	    Log.i("K", "start uploading the check-in.");
	    
	    // add values and using library
	    MultipartEntity entity = new MultipartEntity();
	    
	    try {
	    	entity.addPart("check_share_id", new StringBody(String.valueOf(shareID)));
			entity.addPart("check_date", new StringBody(String.valueOf(date / 1000)));
		 	entity.addPart("check_user_id", new StringBody(String.valueOf(mPref.getInt("user_id", 1)))); // temporarily insert 1.
        	
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	   
	    httppost.setEntity(entity);
	    HttpResponse response = null;
	    responseResult = "";	
	    try {
			response = httpclient.execute(httppost);
			if (response != null) {
				if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				
					BufferedReader br = null;
					try {
						br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
					} catch (IllegalStateException e) {
						Log.i("K", "doInBackground: bufferedReader failed. Illegal.");
						e.printStackTrace();
					} catch (IOException e) {
						Log.i("K",  "doInBackground: bufferedReader failed. IOException.");
						e.printStackTrace();
					} 
					
					try {
						for(;;) {
							String line = br.readLine();
							
							Log.i("K", "line :" + line);
							
							if(line == null) {
								responseResult = "UPLOADED_FAILED";
								Log.i("K", "doInBackground: Upload failed");
								break;
							}
							
							if(line.equals("UPLOADED_OK")) {
								responseResult = "UPLOADED_OK";
								Log.i("K", "doInBackground: Upload ok");
								
								Toast.makeText(mContext, "Check-in this place", Toast.LENGTH_SHORT).show();
								
								break;
							}
						}
					
					} catch (IOException e) {
						Log.i("K", "doInBackground: br.readLine() failed IOException.");
						e.printStackTrace();
					}
				} 
				else {
					Log.i("K", "doInBackground: NOT SC_OK");				
				}
			} 
		} catch (ClientProtocolException e) {
			//e.printStackTrace();
			
		} catch (IOException e) {
			//e.printStackTrace();
		}
	}
	
	/**
	 * Upload comment handler
	 * @param shareID : the id corresponds to the photo.
	 * @param date : date added
	 * @param comment : comment contents
	 */
	public void uploadComments(int shareID, long date, String comment) {

		if (Looper.myLooper() == null)
			Looper.prepare();
		
		HttpClient httpclient = new DefaultHttpClient();  		    
	    String url = new String(Constants.UPLOAD_MY_COMMENT);
	    HttpPost httppost = new HttpPost(url);
	    
	    
	    Log.i("K", "start uploading the comment.");
	    
	    // add values and using library
	    MultipartEntity entity = new MultipartEntity();
	    
	    try {
	    	entity.addPart("c_share_id", new StringBody(String.valueOf(shareID)));
			entity.addPart("c_date", new StringBody(String.valueOf(date / 1000)));
		 	entity.addPart("c_description", new StringBody(comment));
		 	entity.addPart("c_user_id", new StringBody(String.valueOf(mPref.getInt("user_id", 1)))); // temporarily insert 1.
        	
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	   
	    httppost.setEntity(entity);
	    HttpResponse response = null;
	    responseResult = "";	
	    try {
			response = httpclient.execute(httppost);
			if (response != null) {
				if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				
					BufferedReader br = null;
					try {
						br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
					} catch (IllegalStateException e) {
						Log.i("K", "doInBackground: bufferedReader failed. Illegal.");
						e.printStackTrace();
					} catch (IOException e) {
						Log.i("K",  "doInBackground: bufferedReader failed. IOException.");
						e.printStackTrace();
					} 
					
					try {
						
						for(;;) {
							String line = br.readLine();
							
							Log.i("K", "line :" + line);
							
							if(line == null) {
								responseResult = "UPLOADED_FAILED";
								Log.i("K", "doInBackground: Upload failed");
								break;
							}
							
							if(line.equals("UPLOADED_OK")) {
								responseResult = "UPLOADED_OK";
								Log.i("K", "doInBackground: Upload ok");
								break;
							}
						}
					
					} catch (IOException e) {
						Log.i("K", "doInBackground: br.readLine() failed IOException.");
						e.printStackTrace();
					}
				} 
				else {
					Log.i("K", "doInBackground: NOT SC_OK");				
				}
			} 
		} catch (ClientProtocolException e) {
			//e.printStackTrace();
			
		} catch (IOException e) {
			//e.printStackTrace();
		}
	}
	
	/**
	 * Class for share uploader
	 * @author kyunghan
	 *
	 */
	class Uploader extends AsyncTask<Void, Void, Void>{
 
		int eventID;
		boolean facebook;
		
		public Uploader(int eventID, boolean facebook) {
			this.eventID = eventID;
			this.facebook = facebook;
		}
		
	  	@Override
	  	protected Void doInBackground(Void ... unused) {
	  		
	  		ShareItem item = new ShareItem();
	  		item = mDB.getSingleShareMe(eventID);
	  		
	  		
	  		HttpClient httpclient = new DefaultHttpClient();  		    
		    String url = new String(Constants.UPLOAD_MY_SHARE_INFO);
		    HttpPost httppost = new HttpPost(url);
		    
		    // add values and using library
		    MultipartEntity entity = new MultipartEntity();
		 
		    int user_id = mPref.getInt("user_id", 1);
		    
		    try {
				entity.addPart("e_date", new StringBody(String.valueOf(Long.parseLong(item.getEventDate()) / 1000)));
			 	entity.addPart("e_description", new StringBody(item.getEventDescription()));
			 	entity.addPart("e_user_id", new StringBody(String.valueOf(user_id)));
	        	entity.addPart("e_category", new StringBody(item.getEventCategory()));
	        	entity.addPart("e_latitude", new StringBody(String.valueOf(item.getEventLatitude())));
	        	entity.addPart("e_longitude", new StringBody(String.valueOf(item.getEventLongitude())));
	        	entity.addPart("e_accuracy", new StringBody(String.valueOf(item.getEventAccuracy())));
	        	
	        	File file = new File(item.getEventPhotoUrl());
			    if(file.exists()) {
			    	Log.i("K", "=============FILE IS IN THE SDCARD=============");
			    	entity.addPart("image", new FileBody(file));
			    }
			} catch (UnsupportedEncodingException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		   
		    httppost.setEntity(entity);
		    HttpResponse response = null;
		    responseResult = "";	
		    try {
				response = httpclient.execute(httppost);
				if (response != null) {
					if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
					
						BufferedReader br = null;
						try {
							br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
						} catch (IllegalStateException e) {
							Log.i("K", "doInBackground: bufferedReader failed. Illegal.");
							e.printStackTrace();
						} catch (IOException e) {
							Log.i("K",  "doInBackground: bufferedReader failed. IOException.");
							e.printStackTrace();
						} 
						
						try {
							
							for(;;) {
								String line = br.readLine();
								
								Log.i("K", "line :" + line);
								
								if(line == null) {
									responseResult = "UPLOADED_FAILED";
									Log.i("K", "doInBackground: Upload failed");
									break;
								}
								
								if(line.equals("UPLOADED_OK")) {
									responseResult = "UPLOADED_OK";
									Log.i("K", "doInBackground: Upload ok");
									break;
								}
							}
						
						} catch (IOException e) {
							Log.i("K", "doInBackground: br.readLine() failed IOException.");
							e.printStackTrace();
						}
					} 
					else {
						Log.i("K", "doInBackground: NOT SC_OK");				
					}
				} 
			} catch (ClientProtocolException e) {
				//e.printStackTrace();
				
			} catch (IOException e) {
				//e.printStackTrace();
			}
				
			///////////////////////////////////////////////	
			// Upload to Facebook
			//
			//
			///////////////////////////////////////////////
			Log.i("K", "Start uploading to Facebook!");

			//Bundle params = new Bundle();
			//params.putString("method", "photos.upload");
			//params.putByteArray("message", "ooooooooooooooooooooooooooooo".getBytes());
			//mAsyncRunner.request(null, params, "POST", new SampleUploadListener(), null);
			//mAsyncRunner.request(params, new WallPostRequestListener());
			
			if(facebook) {
				uploadToFacebook(item);
			}
	
            return null;
	  	}
	  	
	  	@Override
	  	protected void onPostExecute(Void unused) {
	  		if (responseResult.equals("UPLOADED_OK")) {
	  			//Toast.makeText(mContext, "Successfully uploaded user study data.", Toast.LENGTH_SHORT).show();
	  			uploadCompleteNotification();
	  			mDB.updateShareMe(mEventID);
	  		}
	  			
	  		else
	  			Toast.makeText(mContext, "Failed to upload user study data.", Toast.LENGTH_SHORT).show();
	  	}
	  	
	  	private void uploadToFacebook(ShareItem item) {
	  		
	  		Bundle params = new Bundle();
            params.putString("method", "photos.upload");

            URL uploadFileUrl = null;
            
            String revisedImagePath = item.getEventPhotoUrl().replace("/mnt/sdcard/DCIM/Camera/", "").replace("/sdcard/civicinity/photos/", "");
            
            Log.i("K", "revisedImagePath : " + revisedImagePath);
            
            try {
                uploadFileUrl = new URL(
                    "http://cscl.ist.psu.edu/civicinity/mobile_handler/image_files/thumb_1_" + revisedImagePath); // 1 here is temporal value.
                
                Log.i("K", "uploadFileUrl : " + uploadFileUrl);
            } catch (MalformedURLException e) {
            	e.printStackTrace();
            }
            try {
                HttpURLConnection conn= (HttpURLConnection)uploadFileUrl.openConnection();
                conn.setDoInput(true);
                conn.connect();
                int length = conn.getContentLength();

                byte[] imgData = new byte[length];
                InputStream is = conn.getInputStream();
                is.read(imgData);
                params.putByteArray("picture", imgData);

            } catch  (IOException e) {
                e.printStackTrace();
            }
            //params.putByteArray("message", item.getEventDescription().getBytes());
            //params.putByteArray("description", "This is a description".getBytes());
            
            
            Log.i("K", "File from sdcard : " + item.getEventPhotoUrl());
            params.putString("caption", item.getEventDescription());
            String link = "http://cscl.ist.psu.edu/civicinity/mobile_handler/image_files/1_" + revisedImagePath;
            params.putString("link", link);
            
			// call saved session and make the session in Facebook instance valid.
	        Facebook mFacebook = new Facebook(Constants.FACEBOOK_APP_ID);
	        SessionStore.restore(mFacebook, mContext);
			Log.i("K", "IS session valid: " + mFacebook.isSessionValid());
			
			try {
				mAsyncRunner = new AsyncFacebookRunner(mFacebook);
	            mAsyncRunner.request(null, params, "POST", new SampleUploadListener(), null);
			}
			catch(Exception e) {
				e.printStackTrace();
			}
	  	}
	}
	
	  public class WallPostRequestListener extends BaseRequestListener {

	        public void onComplete(final String response, final Object state) {
	            Log.d("Facebook-Example", "Got response: " + response);
	            String message = "<empty>";
	            try {
	                JSONObject json = Util.parseJson(response);
	                message = json.getString("message");
	            } catch (JSONException e) {
	                Log.w("Facebook-Example", "JSON Error in response");
	            } catch (FacebookError e) {
	                Log.w("Facebook-Example", "Facebook Error: " + e.getMessage());
	            }
	            final String text = "Your Wall Post: " + message;
	            
	        }
	    }
	
	  public class SampleUploadListener extends BaseRequestListener {

	        public void onComplete(final String response, final Object state) {
	            try {
	                // process the response here: (executed in background thread)
	                Log.d("Facebook-Example", "Response: " + response.toString());
	                JSONObject json = Util.parseJson(response);
	                final String src = json.getString("src");

	            } catch (JSONException e) {
	                Log.w("Facebook-Example", "JSON Error in response");
	            } catch (FacebookError e) {
	                Log.w("Facebook-Example", "Facebook Error: " + e.getMessage());
	            }
	        }
	    }
	
	
	
	/**
	 * Class for event uploader
	 * @author kyunghan
	 *
	 */
	class UploaderEvent extends AsyncTask<Void, Void, Void> {

		private int eventID;
		private double latitude;
		private double longitude;
		private float accuracy;
		private String imagePath;
		
		public UploaderEvent(int eventID, double latitude, double longitude, float accuracy, String imagePath) {
			this.eventID = eventID;
			this.latitude = latitude;
			this.longitude = longitude;
			this.accuracy = accuracy;
			this.imagePath = imagePath;
		}
		
		@Override
		protected Void doInBackground(Void... params) {
			// TODO Auto-generated method stub
			
			HttpClient httpclient = new DefaultHttpClient();  		    
		    String url = new String(Constants.UPLOAD_EVENT);
		    HttpPost httppost = new HttpPost(url);
		    
		    Log.i("K", "start uploading like.");
		    
		    // add values and using library
		    MultipartEntity entity = new MultipartEntity();
		    
		    long currentTime = System.currentTimeMillis();
		    
		    try {
		    	entity.addPart("event_id", new StringBody(String.valueOf(eventID)));
			 	entity.addPart("user_id", new StringBody(String.valueOf(1))); // temporarily insert 1.
			 	entity.addPart("date", new StringBody(String.valueOf(currentTime / 1000)));
			 	entity.addPart("latitude", new StringBody(String.valueOf(latitude)));
			 	entity.addPart("longitude", new StringBody(String.valueOf(longitude)));
			 	entity.addPart("accuracy", new StringBody(String.valueOf(accuracy)));
	        	
			 	File file = new File(imagePath);
			    if(file.exists()) {
			    	Log.i("K", "=============FILE IS IN THE SDCARD=============");
			    	entity.addPart("image", new FileBody(file));
			    }
			 	
			} catch (UnsupportedEncodingException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		   
		    httppost.setEntity(entity);
		    HttpResponse response = null;
		    responseResult = "";	
		    try {
				response = httpclient.execute(httppost);
				if (response != null) {
					if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
					
						BufferedReader br = null;
						try {
							br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
						} catch (IllegalStateException e) {
							Log.i("K", "doInBackground: bufferedReader failed. Illegal.");
							e.printStackTrace();
						} catch (IOException e) {
							Log.i("K",  "doInBackground: bufferedReader failed. IOException.");
							e.printStackTrace();
						} 
						
						try {
							
							for(;;) {
								String line = br.readLine();
								
								Log.i("K", "line :" + line);
								
								if(line == null) {
									responseResult = "UPLOADED_FAILED";
									Log.i("K", "doInBackground: Upload failed");
									break;
								}
								
								if(line.equals("UPLOADED_OK")) {
									responseResult = "UPLOADED_OK";
									Log.i("K", "doInBackground: Upload ok");
									break;
								}
							}
						
						} catch (IOException e) {
							Log.i("K", "doInBackground: br.readLine() failed IOException.");
							e.printStackTrace();
						}
					} 
					else {
						Log.i("K", "doInBackground: NOT SC_OK");				
					}
				} 
			} catch (ClientProtocolException e) {
				//e.printStackTrace();
				
			} catch (IOException e) {
				//e.printStackTrace();
			}
			
			return null;
		}
		
	  	@Override
	  	protected void onPostExecute(Void unused) {
	  		if (responseResult.equals("UPLOADED_OK")) {
	  			//Toast.makeText(mContext, "Successfully uploaded user photo.", Toast.LENGTH_SHORT).show();
	  			uploadCompleteNotification();
	  		}
	  		else
	  			Toast.makeText(mContext, "Failed to upload user photo.", Toast.LENGTH_SHORT).show();
	  	}
	}
	
	/**
	 * show the notification message when finishing uploading the photo. (Successfully)
	 */
	private void uploadCompleteNotification() {
		// show notification for the updated news.
    	NotificationManager notificationMgr = (NotificationManager)mContext.getSystemService(mContext.NOTIFICATION_SERVICE);
    	Notification noti = new Notification(R.drawable.civicinity_logo, "[Civicinity] Photo uploaded", System.currentTimeMillis());
		noti.flags |= Notification.FLAG_AUTO_CANCEL;

		PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, null, PendingIntent.FLAG_CANCEL_CURRENT);
		noti.setLatestEventInfo(mContext, "Civicinity", "[Civicinity] Photo uploaded", contentIntent);
		notificationMgr.notify(820713, noti);
	}
}